#include<functional>
#include<iostream>
using namespace std;

template<typename HandlerT>
class FuncTraits: public FuncTraits<decltype(&remove_reference<HandlerT>::type::operator())> { };

template <typename TP>
class FuncTraits<void (&)(TP*)>{
public:
    using ParamType = TP;
};

template <typename C, typename TP>
class FuncTraits<void (C::*)(TP*)>{
public:
    using ParamType = TP;
};

template <typename C, typename TP>
class FuncTraits<void (C::*)(TP*) const>{
public:
    using ParamType = TP;
};

template<typename TB, typename ... TFs>
void handleFunction(TB* param, TFs ... otherFuncs){
    cout<<"No func matched"<<endl;
};

template<typename TB, typename TF, typename ...TFs>
void handleFunction(TB* param, TF func, TFs... otherFuncs){
    auto real_param = dynamic_cast<typename FuncTraits<TF>::ParamType*>(param);
    if(real_param){
        func(real_param);
    } else {
        handleFunction(param, otherFuncs...);
    }
}

class Base {
public:
    virtual void show() = 0;
};

class A : public Base {
public:
    virtual void show() override {
        cout<<"From Class A"<<endl;
    }
};


class B : public Base {
public:
    virtual void show() override {
        cout<<"From Class B"<<endl;
    }
};

template<typename TB, typename TC>
void matchShow(TB* param, function<void(TC*)> func){
    auto real_param = dynamic_cast<TC*>(param);
    if(real_param){
        func(real_param);
    } else {
        cout<<"not matched!"<<endl;
    }
}

int main(){
    B a;
    Base* b = &a;
    function<void(B*)> handle1{[](B* v){ v->show(); }};
    handleFunction(b, handle1, [](A* v){ v->show(); });
    //matchShow(b, handle1);
    //matchShow(b, handle2);
    return 0;
}
